﻿using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging.Messages;
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.Win32;
using Serilog;
using System;
using System.Collections.Generic;
using System.Diagnostics.Eventing.Reader;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using TMI85303.UI.Messages;
using TMI85303.Utils;
using System.Reflection.Metadata;
using Microsoft.VisualBasic;
using ScottPlot;
using System.Data.Entity.Infrastructure;

namespace TMI85303.UI.ViewModels
{
    public partial class TextBoxValue : ObservableObject
    {
        [ObservableProperty]
        private string? value;
    }

    public partial class EEPROMData : ObservableObject
    {
        public List<TextBoxValue> TextBoxValues { get; set; }

        public string? this[int index]
        {
            get { return TextBoxValues[index].Value; }
            set
            {
                if (TextBoxValues[index].Value != value) TextBoxValues[index].Value = value;
            }
        }


        [ObservableProperty]
        private bool isCheckedMTP0 = false;
        [ObservableProperty]
        private bool isCheckedMTP1 = false;
        [ObservableProperty]
        private bool isCheckedMTP2 = false;
        [ObservableProperty]
        private bool isCheckedMTP3 = false;
        [ObservableProperty]
        private bool isCheckedMTP4 = false;
        [ObservableProperty]
        private bool isCheckedMTP5 = false;
        [ObservableProperty]
        private bool isCheckedMTP6 = false;
        [ObservableProperty]
        private bool isCheckedMTP7 = false;
        [ObservableProperty]
        private bool isCheckedMTP8 = false;
        [ObservableProperty]
        private bool isCheckedMTP9 = false;
        [ObservableProperty]
        private bool isCheckedMTP10 = false;
        [ObservableProperty]
        private bool isCheckedMTP11 = false;
        [ObservableProperty]
        private bool isCheckedMTP12 = false;
        [ObservableProperty]
        private bool isCheckedMTP13 = false;
        [ObservableProperty]
        private bool isCheckedMTP14 = false;
        [ObservableProperty]
        private bool isCheckedMTP15 = false;
        [ObservableProperty]
        private bool isCheckedMTP16 = false;
        [ObservableProperty]
        private bool isCheckedMTP17 = false;
        [ObservableProperty]
        private bool isCheckedMTP18 = false;
        [ObservableProperty]
        private bool isCheckedMTP19 = false;
        [ObservableProperty]
        private bool isCheckedMTP20 = false;
        [ObservableProperty]
        private bool isCheckedMTP21 = false;
        [ObservableProperty]
        private bool isCheckedMTP22 = false;
        [ObservableProperty]
        private bool isCheckedMTP23 = false;
        [ObservableProperty]
        private bool isCheckedMTP24 = false;
        [ObservableProperty]
        private bool isCheckedMTP25 = false;
        [ObservableProperty]
        private bool isCheckedMTP26 = false;
        [ObservableProperty]
        private bool isCheckedMTP27 = false;
        //[ObservableProperty]
        //private bool isCheckedMTP28 = false;
        [ObservableProperty]
        private bool isCheckedMTP29 = false;
        [ObservableProperty]
        private bool isCheckedMTP30 = false;
        //[ObservableProperty]
        //private bool isCheckedMTP31 = false;

        //寄存器的总个数
        private static readonly int RegisterNum = 32;

        [ObservableProperty]
        private string? filePath;

        public const string CheckSumInvalid = "----";
        [ObservableProperty]
        private string? mTPCheckSumResult= CheckSumInvalid;
        [ObservableProperty]
        private string? shadowCheckSumResult = CheckSumInvalid;

        public EEPROMData() 
        {
            TextBoxValues = new();
            for (int i = 0; i < RegisterNum; i++)
            {
                TextBoxValues.Add(new TextBoxValue() { Value = "" });
            }

            WeakReferenceMessenger.Default.Register<ReadFileMTPDataConfig, int>(this, (int)MesgToken.MTP_DATA, OnReadConfig);
            WeakReferenceMessenger.Default.Register<WriteFileMTPDataConfig, int>(this, (int)MesgToken.MTP_DATA, OnWriteConfig);
            WeakReferenceMessenger.Default.Register<UpdateMTPDataMesg, int>(this, (int)MesgToken.MTP_DATA, OnUpdateMTPData);
            SelectAllOrNotAll(true);
        }

        private void OnUpdateMTPData(object recipient, UpdateMTPDataMesg message)
        {
            if(message.Index32Reg >= 0 && message.Index32Reg <= 31)
            {
                TextBoxValues[message.Index32Reg].Value = message.NewData.ToString("X4");
            }
        }

        private void OnWriteConfig(object recipient, WriteFileMTPDataConfig message)
        {
            try
            {
                for (ushort i = 0; i < TextBoxValues.Count; i++)
                {
                    IniFile.WriteSetting(PathHelper.IniPath, "MTP Data", $"MTP{i}", TextBoxValues[i].Value ?? "");
                }
            }
            catch (Exception)
            {
                Log.Information("自动保存MTP数据失败！");
            }

            if (ReadWrite.ConnectedOk)
            {
                ReadWrite.WriteRegNoLog(165, 0, 2);
                ReadWrite.DisConnectDev();
            }
        }

        private void OnReadConfig(object recipient, ReadFileMTPDataConfig message)
        {
            for (int index = 0; index < RegisterNum; index++)
            {
                TextBoxValues[index].Value = IniFile.ReadSetting(PathHelper.IniPath, "MTP Data", $"MTP{index}", "0000");
                if (int.TryParse(TextBoxValues[index].Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var newValue))
                {
                    WeakReferenceMessenger.Default.Send<UpdateRegisterMesg, int>(new(index, newValue), (int)MesgToken.RegVMToken);
                }
                else
                {
                    Log.Information($"MTP{index}：从配置文件读取值解析失败!");
                }
            }
        }

        [RelayCommand]
        private void ReadMTP(object index)
        {
            var buttonNumber = Convert.ToUInt16(index);
            //if (!isCanExc(buttonNumber)) return;
            if (buttonNumber == 28 || buttonNumber == 31) return;//地址28 31是MTP的加密数据，不用读取
            int readRes = ReadWrite.ReadEE(buttonNumber);
            TextBoxValues[buttonNumber].Value = readRes.ToString("X4");
            WeakReferenceMessenger.Default.Send<UpdateRegisterMesg, int>(new(buttonNumber, readRes), (int)MesgToken.RegVMToken);
        }

        [RelayCommand]
        private void WriteMTP(object index)
        {
            int buttonNumber = Convert.ToInt32(index);
            if (buttonNumber == 28 || buttonNumber == 31) return;//地址28 31是MTP的加密数据

            MainWindowVM.MTPchackFailed = false;
            Log.Information(" Write MTP:\r\n");

            //int EE28Data = ReadWrite.ReadEENoLog(28);
            //int EE31Data = ReadWrite.ReadEENoLog(31);

            /****全片擦除****/
            //ReadWrite.WriteReg(166, 0x8000, 2);
            //ReadWrite.WriteReg(190, 0x01C0, 2);
            //Thread.Sleep(10);
            //ReadWrite.WriteReg(166, 0x0000, 2);
            //ReadWrite.WriteReg(190, 0x0000, 2);
            //ReadWrite.WriteEENoLog(28, EE28Data);
            //ReadWrite.WriteEENoLog(31, EE31Data);

            if (!int.TryParse(TextBoxValues[buttonNumber].Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var newVal))
            {
                Log.Information("写值失败：请输入正确的十六进制数");
                return;
            }
            ReadWrite.WriteEE(buttonNumber, newVal);
            if (MainWindowVM.MTPchackFailed)
            {
                MessageBox.Show("MTP Write failure!\r\nPlease check whether the Program supply voltage is correct?");
                Log.Information("MTP Write failure!\r\n");
            }
            else
            {
                WeakReferenceMessenger.Default.Send<UpdateRegisterMesg, int>(new(buttonNumber, newVal), (int)MesgToken.RegVMToken);
                Log.Information("MTP Write successfully!\r\n");
            }
        }

        [RelayCommand]
        private void ReadShadow(object index)
        {
            var buttonNumber = Convert.ToUInt16(index);
            //if (!isCanExc(buttonNumber)) return;
            int readRes = ReadWrite.ReadReg((ushort)(buttonNumber + 64), 2);
            TextBoxValues[buttonNumber].Value = readRes.ToString("X4");
            WeakReferenceMessenger.Default.Send<UpdateRegisterMesg, int>(new(buttonNumber, readRes), (int)MesgToken.RegVMToken);

        }

        [RelayCommand]
        private void WriteShadow(object index)
        {
            if(index is string indexStr && ushort.TryParse(indexStr, out var buttonNumber))
            {
                if (buttonNumber == 28 || buttonNumber == 31) return;//地址28 31是MTP的加密数据

                if (!int.TryParse(TextBoxValues[buttonNumber].Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var newVal))
                {
                    Log.Information("写值失败：请输入正确的十六进制数");
                    return;
                }
                ReadWrite.WriteReg((ushort)(buttonNumber + 64), newVal, 2);
                WeakReferenceMessenger.Default.Send<UpdateRegisterMesg, int>(new(buttonNumber, newVal), (int)MesgToken.RegVMToken);
            }
        }

        [RelayCommand]
        private void ReadAllMTP()
        {
            try
            {
                Log.Information(" 读MTP:\r\n");
                Log.Information(" (MTP 地址 : MTP 数据)\r\n");
                int[] res = new int[TextBoxValues.Count];
                for (ushort i = 0;i < TextBoxValues.Count; i++)
                {
                    if (i == 28 || i == 31) continue;//地址28 31是MTP的加密数据，不用读取
                    if (!isCanExc(i)) continue;
                    res[i] = ReadWrite.ReadEE(i);
                    WeakReferenceMessenger.Default.Send<UpdateRegisterMesg, int>(new(i, res[i]), (int)MesgToken.RegVMToken);

                    TextBoxValues[i].Value = res[i].ToString("X4");
                }
                Log.Information("\r\n");
            }
            catch
            {
                return;
            }
        }

        [RelayCommand]
        private void ReadAllShadow()
        {
            try
            {
                int[] res = new int[TextBoxValues.Count];
                for (ushort inndx = 0, readAddrShadow = 64; inndx < TextBoxValues.Count && readAddrShadow < 96; inndx++, readAddrShadow++)
                {
                    if (inndx != 28 && inndx != 31 && !isCanExc(inndx)) continue;
                    res[inndx] = ReadWrite.ReadReg(readAddrShadow, 2);
                    WeakReferenceMessenger.Default.Send<UpdateRegisterMesg, int>(new(inndx, res[inndx]), (int)MesgToken.RegVMToken);
                    TextBoxValues[inndx].Value = res[inndx].ToString("X4");
                }
                Log.Information("\r\n");
            }
            catch
            {
                return;
            }
        }

        [RelayCommand]
        private void WriteAllMTP()
        {
            MainWindowVM.MTPchackFailed = false;
            ////读MTP
            //int EE28Data = ReadWrite.ReadEENoLog(28);
            //int EE31Data = ReadWrite.ReadEENoLog(31);
            //Log.Information(" 写MTP:\r\n");
            ///****全片擦除****/
            //ReadWrite.WriteReg(166, 0x8000, 2);
            //ReadWrite.WriteReg(190, 0x01C0, 2);
            //Thread.Sleep(10);
            //ReadWrite.WriteReg(166, 0x0000, 2);
            //ReadWrite.WriteReg(190, 0x0000, 2);
            ///***************/
            ////写MTP
            //ReadWrite.WriteEENoLog(28, EE28Data);
            //ReadWrite.WriteEENoLog(31, EE31Data);

            for (int i = 0; i < TextBoxValues.Count; i++)
            {
                if(i == 28 || i == 31)
                {
                    Log.Information(" 跳过地址" + i + "\r\n");
                    continue;
                }
                if (!isCanExc(i)) continue;

                if (int.TryParse(TextBoxValues[i].Value, NumberStyles.HexNumber, null, out var writeData))
                {
                    ReadWrite.WriteEE(i, writeData);
                    WeakReferenceMessenger.Default.Send<UpdateRegisterMesg, int>(new(i, writeData), (int)MesgToken.RegVMToken);
                }
            }
            Log.Information("\r\n");
        }

        [RelayCommand]
        private void WriteAllShadow()
        {
            for (int i = 0; i < TextBoxValues.Count; i++)
            {
                if (i == 28 || i == 31)
                {
                    Log.Information(" 跳过地址" + (i + 64) + "\r\n");
                    continue;
                }
                if (!isCanExc(i)) continue;

                if (int.TryParse(TextBoxValues[i].Value, NumberStyles.HexNumber, null, out var writeData))
                {
                    ReadWrite.WriteReg((ushort)(i + 64), writeData, 2);
                    WeakReferenceMessenger.Default.Send<UpdateRegisterMesg, int>(new(i, writeData), (int)MesgToken.RegVMToken);
                }
            }
            Log.Information("\r\n");
        }

        [RelayCommand]
        private void Input()
        {
            string openPath = FileHelper.IsExistDirectory(PathHelper.DubugConfigFolder) ? 
                PathHelper.DubugConfigFolder : 
                Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);

            OpenFileDialog openFileDialog = new() 
            {
                Filter = "ini文件|*.ini",
                InitialDirectory = openPath
            };

            if (openFileDialog.ShowDialog() == true)
            {
                FilePath = openFileDialog.FileName;
                for (int index = 0; index < TextBoxValues.Count; index++)
                {
                    TextBoxValues[index].Value = IniFile.ReadSetting(FilePath, "MTP Data", $"MTP{index}", "0000");
                    if (int.TryParse(TextBoxValues[index].Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var newValue))
                    {
                        WeakReferenceMessenger.Default.Send<UpdateRegisterMesg, int>(new(index, newValue), (int)MesgToken.RegVMToken);
                    }
                    else
                    {
                        Log.Information($"MTP{index}：从配置文件读取值解析失败!");
                    }
                }
                MessageBox.Show("数据已导入", "提示");
            }
        }

        [RelayCommand]
        private void Export()
        {
            string openPath = FileHelper.IsExistDirectory(PathHelper.DubugConfigFolder) ?
                                PathHelper.DubugConfigFolder :
                                Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);

            SaveFileDialog saveFileDialog2 = new()
            {
                Filter = "ini文件|*.ini",
                FileName = "ParameterFile_TMI85303_" + DateTime.Now.ToString("yyMMdd_HHmm"),
                InitialDirectory = openPath
            };


            if (saveFileDialog2.ShowDialog() == true)
            {
                FilePath = saveFileDialog2.FileName;
                for (int i = 0; i < TextBoxValues.Count; i++)
                {
                    IniFile.WriteSetting(FilePath, "MTP Data", $"MTP{i}", TextBoxValues[i].Value);
                }

                MessageBox.Show("数据已导出", "提示", MessageBoxButton.OK);
            }
        }

        [RelayCommand]
        private void Clear()
        {
            foreach (var item in TextBoxValues)
            {
                item.Value = "";
            }
        }

        [RelayCommand]
        private void SelectAllOrNotAll(object parameter)
        {
            if (parameter is not bool isChecked) return;

            IsCheckedMTP8 = isChecked;
            IsCheckedMTP9 = isChecked;
            IsCheckedMTP10 = isChecked;
            IsCheckedMTP11 = isChecked;
            IsCheckedMTP12 = isChecked;
            IsCheckedMTP13 = isChecked;
            IsCheckedMTP14 = isChecked;
            IsCheckedMTP15 = isChecked;
            IsCheckedMTP16 = isChecked;
            IsCheckedMTP17 = isChecked;
            IsCheckedMTP18 = isChecked;
            IsCheckedMTP19 = isChecked;
            IsCheckedMTP20 = isChecked;
            IsCheckedMTP21 = isChecked;
            IsCheckedMTP22 = isChecked;
            IsCheckedMTP23 = isChecked;
            IsCheckedMTP24 = isChecked;
            IsCheckedMTP25 = isChecked;
            IsCheckedMTP26 = isChecked;
            IsCheckedMTP27 = isChecked;
            //IsCheckedMTP28 = isChecked;
            IsCheckedMTP29 = isChecked;
            IsCheckedMTP30 = isChecked;
            //IsCheckedMTP31 = isChecked;
        }

        [RelayCommand]
        private void SelectInvert()
        {
            IsCheckedMTP8 = !IsCheckedMTP8;
            IsCheckedMTP9 = !IsCheckedMTP9;
            IsCheckedMTP10 = !IsCheckedMTP10;
            IsCheckedMTP11 = !IsCheckedMTP11;
            IsCheckedMTP12 = !IsCheckedMTP12;
            IsCheckedMTP13 = !IsCheckedMTP13;
            IsCheckedMTP14 = !IsCheckedMTP14;
            IsCheckedMTP15 = !IsCheckedMTP15;
            IsCheckedMTP16 = !IsCheckedMTP16;
            IsCheckedMTP17 = !IsCheckedMTP17;
            IsCheckedMTP18 = !IsCheckedMTP18;
            IsCheckedMTP19 = !IsCheckedMTP19;
            IsCheckedMTP20 = !IsCheckedMTP20;
            IsCheckedMTP21 = !IsCheckedMTP21;
            IsCheckedMTP22 = !IsCheckedMTP22;
            IsCheckedMTP23 = !IsCheckedMTP23;
            IsCheckedMTP24 = !IsCheckedMTP24;
            IsCheckedMTP25 = !IsCheckedMTP25;
            IsCheckedMTP26 = !IsCheckedMTP26;
            IsCheckedMTP27 = !IsCheckedMTP27;
            //IsCheckedMTP28 = !IsCheckedMTP28;
            IsCheckedMTP29 = !IsCheckedMTP29;
            IsCheckedMTP30 = !IsCheckedMTP30;
            //IsCheckedMTP31 = !IsCheckedMTP31;
        }

        [RelayCommand]
        private void Select0_6(object parameter)
        {
            if (parameter is not bool isChecked) return;

            IsCheckedMTP0 = isChecked;
            IsCheckedMTP1 = isChecked;
            IsCheckedMTP2 = isChecked;
            IsCheckedMTP3 = isChecked;
            IsCheckedMTP4 = isChecked;
            IsCheckedMTP5 = isChecked;
            IsCheckedMTP6 = isChecked;
        }

        [RelayCommand]
        private void ShowMTPCheckSum() => MTPCheckSumResult = UpdateCheckSum();

        [RelayCommand]
        private void ShowShadowCheckSum() => ShadowCheckSumResult = UpdateCheckSum();


        private bool isCanExc(int index)
        {
            return index switch
            {
                0 => IsCheckedMTP0,
                1 => IsCheckedMTP1,
                2 => IsCheckedMTP2,
                3 => IsCheckedMTP3,
                4 => IsCheckedMTP4,
                5 => IsCheckedMTP5,
                6 => IsCheckedMTP6,
                7 => IsCheckedMTP7,
                8 => IsCheckedMTP8,
                9 => IsCheckedMTP9,
                10 => IsCheckedMTP10,
                11 => IsCheckedMTP11,
                12 => IsCheckedMTP12,
                13 => IsCheckedMTP13,
                14 => IsCheckedMTP14,
                15 => IsCheckedMTP15,
                16 => IsCheckedMTP16,
                17 => IsCheckedMTP17,
                18 => IsCheckedMTP18,
                19 => IsCheckedMTP19,
                20 => IsCheckedMTP20,
                21 => IsCheckedMTP21,
                22 => IsCheckedMTP22,
                23 => IsCheckedMTP23,
                24 => IsCheckedMTP24,
                25 => IsCheckedMTP25,
                26 => IsCheckedMTP26,
                27 => IsCheckedMTP27,
                //28 => IsCheckedMTP28,
                29 => IsCheckedMTP29,
                30 => IsCheckedMTP30,
                //31 => IsCheckedMTP31,
                _ => false,
            };
        }

        private string UpdateCheckSum()
        {
            bool IsSelectAll()
            {
                return 
                IsCheckedMTP8 &&
                IsCheckedMTP9 &&
                IsCheckedMTP10 &&
                IsCheckedMTP11 &&
                IsCheckedMTP12 &&
                IsCheckedMTP13 &&
                IsCheckedMTP14 &&
                IsCheckedMTP15 &&
                IsCheckedMTP16 &&
                IsCheckedMTP17 &&
                IsCheckedMTP18 &&
                IsCheckedMTP19 &&
                IsCheckedMTP20 &&
                IsCheckedMTP21 &&
                IsCheckedMTP22 &&
                IsCheckedMTP23 &&
                IsCheckedMTP24 &&
                IsCheckedMTP25 &&
                IsCheckedMTP26 &&
                IsCheckedMTP27 &&
                IsCheckedMTP29 &&
                IsCheckedMTP30;
            }

            if (IsSelectAll())
            {
                long sum = 0;
                for (int index = 0; index < TextBoxValues.Count; index++)
                {
                    if (index == 7 || index == 28 || index == 31 || !isCanExc(index)) continue;
                    if (int.TryParse(TextBoxValues[index].Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var val))
                    {
                        sum += val;
                    }
                    else
                    {
                        Log.Information($"校验和计算时，MTP{index}数据转化失败!");
                        return CheckSumInvalid;
                    }
                }
                return "0x" + (sum & 0xFFFF).ToString("X");
            }
            else return CheckSumInvalid;
        }

    }
}
